package com.mh.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.mh.dao.GroupInfoDao;
import com.mh.dao.GroupUserDao;
import com.mh.dao.UserInfoDao;
import com.mh.dto.R;
import com.mh.dto.vo.GroupApplyHandleVo;
import com.mh.dto.vo.GroupIntoVo;
import com.mh.dto.vo.GroupUserDto;
import com.mh.pojo.GroupInfo;
import com.mh.pojo.GroupUser;
import com.mh.pojo.UserInfo;
import com.mh.service.GroupUserService;
import org.apache.catalina.User;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;
import java.util.*;

/**
 * 群组用户表(GroupUser)表服务实现类
 *
 * @author zmh
 * @since 2024-09-02 17:22:06
 */
@Service
public class GroupUserServiceImpl extends ServiceImpl<GroupUserDao, GroupUser> implements GroupUserService {

    @Autowired
    private GroupUserDao groupUserDao;

    @Autowired
    private GroupInfoDao groupInfoDao;

    @Autowired
    private UserInfoDao userInfoDao;

    @Resource
    @Qualifier("redisTemplateSet")
    private RedisTemplate<String, Set<String>> redisTemplateSet;

    @Resource
    @Qualifier("redisTemplateMap")
    private RedisTemplate<String, Map<String,String>> redisTemplate;

    /**
     * 分页查询
     *
     * @param page 查询页数
     * @param size 一页显示条数
     * @return ·
     */
    public R<Page<GroupUser>> getAllByPage(int page, int size) {
        Page<GroupUser> groupUserPage = new Page<>(page, size);
        LambdaQueryWrapper<GroupUser> queryWrapper = new LambdaQueryWrapper<>();
        //TODO 查询条件定制
        return R.success(groupUserDao.selectPage(groupUserPage, queryWrapper));
    }

    /**
     * 添加group_user表记录
     * @param groupIntoVo VO：群组ID, 用户ID，状态
     * @return ·
     */
    @Override
    public R<String> groupInto(GroupIntoVo groupIntoVo) {

        // 检查是否是重复申请或是否已经存在于群组之中
        LambdaQueryWrapper<GroupUser> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.eq(GroupUser::getGroupId, groupIntoVo.getGroupId());
        queryWrapper.eq(GroupUser::getUserId, groupIntoVo.getUserId());
        GroupUser groupUser = groupUserDao.selectOne(queryWrapper);

        // 检查是否存在或是否重复申请
        if(groupUser != null && groupUser.getState() == 0 && groupIntoVo.getState() == 0){
            return R.error("请勿重复申请该群组");
        }

        if(groupUser != null && groupUser.getState() == 1 && groupIntoVo.getState() == 0){
           return R.error("您已存在于该群组");
        }

        // 构造【群组-用户】对象记录
        GroupUser groupUser1 = new GroupUser(null, groupIntoVo.getGroupId(),
                groupIntoVo.getUserId(), groupIntoVo.getState());
        int insert = groupUserDao.insert(groupUser1);
        return insert > 0 ? R.success("申请成功") : R.error("申请失败");
    }


    @Override
    public R<List<GroupUserDto>> getUserInfoOfApplyGroup(String userId) {
        // 取出Redis中的所有接收者信息，用来构造返回DTO信息
        Map<String, String> receiverInfos = redisTemplate.opsForValue().get("receiver-info");

        // 根据用户ID找出所有创建的群组信息（作为群组的所有群）
        List<GroupInfo> groupInfos = groupInfoDao.selectList(new LambdaQueryWrapper<GroupInfo>()
                .eq(GroupInfo::getGroupOwner, userId));

        if(groupInfos.isEmpty()) return R.success(new ArrayList<>());

        // 取出所有群组ID为列表
        List<String> groupIds = groupInfos.stream().map(GroupInfo::getGroupId).toList();

        // 遍历所有群组，根据群ID找出state为0的所有记录
        List<GroupUser> groupUsers = groupUserDao.selectList(new LambdaQueryWrapper<GroupUser>()
                .in(GroupUser::getGroupId, groupIds)
                .eq(GroupUser::getState, 0));

        // 返回的DTO列表
        ArrayList<GroupUserDto> groupUserReturns = new ArrayList<>();

        // 遍历groupUsers，从Redis中取出用户名称和群组名称，用来构造返回的DTO
        for (GroupUser groupUser : groupUsers) {
            groupUserReturns.add(new GroupUserDto(groupUser.getGroupId(),
                    receiverInfos.get(groupUser.getGroupId()),groupUser.getUserId(),
                    receiverInfos.get(groupUser.getUserId()), 0));
        }

        return R.success(groupUserReturns);
    }

    @Override
    public R<List<GroupUserDto>> getBeInviteGroupInfo(String userId) {

        // 取出Redis中的所有接收者信息，用来构造返回DTO信息
        Map<String, String> receiverInfos = redisTemplate.opsForValue().get("receiver-info");

        // 取出指定用户ID的所有状态为2的记录
        List<GroupUser> groupUsers = groupUserDao.selectList(new LambdaQueryWrapper<GroupUser>()
                .eq(GroupUser::getUserId, userId)
                .eq(GroupUser::getState, 2));

        // 通过Redis中的接收者信息，构造返回DTO列表
        // 返回的DTO列表
        ArrayList<GroupUserDto> groupUserReturns = new ArrayList<>();

        // 遍历groupUsers，从Redis中取出用户名称和群组名称，用来构造返回的DTO
        for (GroupUser groupUser : groupUsers) {
            groupUserReturns.add(new GroupUserDto(groupUser.getGroupId(),
                    receiverInfos.get(groupUser.getGroupId()),groupUser.getUserId(),
                    receiverInfos.get(groupUser.getUserId()), 2));
        }
        return R.success(groupUserReturns);
    }


    @Override
    public R<String> GroupApplyHandle(GroupApplyHandleVo groupApplyHandleVo) {
        LambdaUpdateWrapper<GroupUser> updateWrapper = new LambdaUpdateWrapper<>();
        updateWrapper.eq(GroupUser::getGroupId, groupApplyHandleVo.getGroupId())
                .eq(GroupUser::getUserId, groupApplyHandleVo.getUserId())
                .set(GroupUser::getState, groupApplyHandleVo.getOps());
        int update = groupUserDao.update(updateWrapper);

        // 动态维护Redis中的群组用户关联信息
        if(groupApplyHandleVo.getOps() == 1){
            // 同意加入，将用户ID加入到群组对应用户列表中
            String redisKey = "chat-group:" + groupApplyHandleVo.getGroupId();
            Set<String> userIds = redisTemplateSet.opsForValue().get(redisKey);
            if(userIds == null) userIds = new HashSet<>();
            userIds.add(groupApplyHandleVo.getUserId());
            redisTemplateSet.opsForValue().set(redisKey, userIds);
        }

        return update > 0 ? R.success("操作成功") : R.error("操作失败");
    }

    @Override
    public R<List<GroupInfo>> getGroupList(String userId) {
        // 根据用户ID找出该用户加入的所有群组ID
        List<GroupUser> groupUsers = groupUserDao.selectList(new LambdaQueryWrapper<GroupUser>()
                .eq(GroupUser::getUserId, userId)
                .eq(GroupUser::getState, 1));

        // 取出公共群组信息返回
        LambdaQueryWrapper<GroupInfo> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.eq(GroupInfo::getGroupNumber, "000000");
        GroupInfo publicGroupInfo = groupInfoDao.selectOne(queryWrapper);

        // 如果用户没有加入任何群组，则直接返回
        if(groupUsers.isEmpty()){
            ArrayList<GroupInfo> groupInfos = new ArrayList<>();
            groupInfos.add(publicGroupInfo);
            return R.success(groupInfos);
//            return R.error("该用户没有加入任何群组");
        }

        // 遍历取出群组ID封装到不重复集合中
        HashSet<String> groupIds = new HashSet<>();
        for (GroupUser groupUser : groupUsers) {
            groupIds.add(groupUser.getGroupId());
        }

        // 根据ids取出所有群组信息
        List<GroupInfo> groupInfos = groupInfoDao.selectList(new LambdaQueryWrapper<GroupInfo>()
                .in(GroupInfo::getGroupId, groupIds));

        groupInfos.add(publicGroupInfo);

        return R.success(groupInfos);
    }

    @Override
    public R<String> inviteUserIntoGroup(String groupId, String email) {
        // 根据邮箱地址找到用户ID
        UserInfo userInfo = userInfoDao.selectOne(new LambdaQueryWrapper<UserInfo>()
                .eq(UserInfo::getEmail, email));
        GroupUser groupUser = new GroupUser(null, groupId, userInfo.getUserId(), 2);

        int insert = groupUserDao.insert(groupUser);
        return insert > 0 ? R.success("邀请成功") : R.error("邀请失败");
    }

}

